package com.cenntro.auth.controllers;

import java.io.Serializable;
import java.util.Comparator;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.cenntro.auth.model.dbo.SysAgentDO;
import com.cenntro.auth.model.dbo.SysPermissionDO;
import com.cenntro.auth.model.dbo.SysRoleDO;
import com.cenntro.auth.model.dbo.SysSooidDO;
import com.cenntro.auth.model.vo.SysSooidAddVO;
import com.cenntro.auth.model.vo.SysSooidDetailVO;
import com.cenntro.auth.model.vo.SysSooidVO;
import com.cenntro.auth.service.SysAgentService;
import com.cenntro.auth.service.SysRoleService;
import com.cenntro.auth.service.SysSooidService;
import com.cenntro.auth.shiro.UserRealm;
import com.cenntro.auth.utils.AgentPathUtil;
import com.cenntro.auth.utils.Valid;
import com.cenntro.common.aliyun.FileUpload;
import com.cenntro.common.base.BaseController;
import com.cenntro.common.exception.BizException;
import com.cenntro.common.model.vo.PageVO;
import com.cenntro.common.util.ConvertorUtils;
import com.cenntro.common.util.MessageDigestUtil;
import com.cenntro.common.util.MessageUtil;
import com.cenntro.common.util.result.PageResult;
import com.cenntro.common.util.result.Result;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import springfox.documentation.annotations.ApiIgnore;

@Api(value = "用户", tags = { "用户" })
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController extends BaseController {

	@Resource
	private SysSooidService sysSooidService;
	@Resource
	private	SecurityManager securityManager;
	@Resource(name="agentService")
	private SysAgentService sysAgentService;
	@Resource
    private SysRoleService sysRoleService;
	
	@ApiOperation(value = "登录", notes = "登录")
	@RequestMapping("/login")
	public Result login(String userName, String password, String registrationId) {
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName, password);
		// 进行验证，这里可以捕获异常，然后返回对应信息
		try{
			subject.login(usernamePasswordToken);
		}catch(Exception e){
			throw new BizException(-1, "登录失败， 请检查帐户和密码");
		}
		
		SysSooidDO user = (SysSooidDO)subject.getPrincipal();  //登 录以后
		
		List<SysRoleDO> roles = sysRoleService.selectByUserId(user.getId());
		if(roles != null && roles.size() > 0){
    		roles.sort(new Comparator<SysRoleDO>() {
    		    @Override
    		    public int compare(SysRoleDO o1, SysRoleDO o2) {
    		        return o1.getRoleType().compareTo(o2.getRoleType());
    		    }
            });
    		user.setRoleType(roles.get(0).getRoleType());  //取到最大的角色。 角色类型对应的权限是包含关系
		}
		
		Serializable seesionId = subject.getSession().getId();
	    SysSooidDO sysSooidDO = new SysSooidDO();
	    //修改登录token
	    sysSooidDO.setToken(seesionId.toString());
	    sysSooidDO.setRegistrationId(registrationId);
	    sysSooidDO.setId(user.getId());
	    sysSooidService.updateSysSooid(sysSooidDO);
		
		SysSooidDetailVO sooid = ConvertorUtils.deepConvert(user, SysSooidDetailVO.class);
		sooid.setToken(seesionId.toString());
		SysAgentDO agent = sysAgentService.selectById(user.getAgentId());
		if(agent != null){
			if(agent.getAgentPath() != null && agent.getAgentPath().startsWith("0")){
				sooid.setCompany(agent.getCompany());
				sooid.setLogo(agent.getLogo());
				sooid.setAgentId(agent.getId());
				sooid.setLinkMan(agent.getLinkMan());
				sooid.setLinkTel(agent.getLinkTel());
			}else {
				String path = agent.getAgentPath();
				String agentId = path.split("-_")[0];
				agent = sysAgentService.selectById(NumberUtils.toInt(agentId));
				if(agent != null){
					sooid.setCompany(agent.getCompany());
					sooid.setLogo(agent.getLogo());
					sooid.setAgentId(agent.getId());
					sooid.setLinkMan(agent.getLinkMan());
					sooid.setLinkTel(agent.getLinkTel());
//					sooid.setHeadpic(sysEmployeeDO.getHeadPic());
					
//					Map<String, String> map = Maps.newHashMap();
//					map.put("sooid", sooid.getSooID());
//					SysEmployeeDO sysEmployeeDO = sysEmployeeService.selectOne(map);
				}
			}
		}
		List<SysPermissionDO> permission = sysSooidService.selectPermissionByUserId(sooid.getId());
		List<String> StringPermissions = Lists.newArrayList();
		for (SysPermissionDO perm : permission){
			StringPermissions.add(perm.getUrl());
		}
		sooid.setStringPermissionList(StringPermissions);
		
		return Result.ok(sooid);
	}
	
	/**
	 * 登出
	 * @param
	 * @return
	 */
	@CrossOrigin
	@ApiOperation(value = "退出", notes = "退出")
	@RequestMapping(value="/logout")
	@ApiModelProperty(value = "退出")
	public Result logout(){
		Subject subject = SecurityUtils.getSubject();
		if(subject != null){
			subject.logout();
		}
		return Result.ok();
	}

	/**
	 * 
	 * @param sysAuthVO
	 * @return
	 */
	@ApiIgnore
	@RequestMapping(value="/unauth")
	public Result unauth(){
		return Result.error("没有权限");
	}
	
	
	/**
	 * 1、新增用户名不能重复
	 * 2、密码不能是空
	 * 
	 * @param SysPermissionVO
	 * @return  
	 */
	@ApiOperation(value = "用户帐户新增", notes = "用户帐户新增")
	@RequestMapping(value="/add")
	public Result add(@Validated(value={Valid.insert.class}) SysSooidAddVO sooidVO, HttpServletRequest req){
		log.info(sooidVO.toString());
		FileUpload upload = new FileUpload();
		String url = upload.upload(req, FileUpload.PREFIX_OSS);
		sooidVO.setHeadPic(url);
		int count = sysSooidService.insert(sooidVO);
		if (count < 0){
			return Result.error(MessageUtil.PARAM_ILLEGAL, MessageUtil.getMsg("PERMISSION_NAME_EXISTS", sooidVO.getUserName()));
		}
		return Result.ok();
	}
	
	/**
	 * 1、新增用户名不能重复
	 * 2、id不能是空
	 * 
	 * @param SysPermissionVO
	 * @return
	 */
	@CrossOrigin
	@ApiOperation(value = "帐户修改", notes = "帐户修改")
	@RequestMapping(value="/update")
	public Result update(@Validated(value={Valid.update.class}) SysSooidAddVO sooidVO){
		log.info(sooidVO.toString());
		
		int count = sysSooidService.update(sooidVO);
		if (count > 0){
			return Result.ok();
		}
		return Result.error(MessageUtil.PARAM_ILLEGAL, MessageUtil.getMsg("USERNAME_EXISTS", sooidVO.getUserName()));  //权限已经存在
	}
	
	/**
	 * 1、新增用户名不能重复
	 * 2、id不能是空
	 * 
	 * @param SysPermissionVO
	 * @return
	 */
	@ApiOperation(value = "用户列表", notes = "用户列表")
	@RequestMapping(value="/selectPage")
	public Result selectPage(SysSooidVO sooidVO, PageVO pageVO){
		Page<SysSooidDO> page = PageHelper.startPage(pageVO.getPage(), pageVO.getLimit(), true);
		SysSooidDO sysSooidDO = ConvertorUtils.deepConvert(sooidVO, SysSooidDO.class);
		sysSooidDO.setStatus(1);
		String agentPath = null;
		if(sooidVO.getAgentId() != null){
		    SysAgentDO sysAgent = sysAgentService.selectById(sooidVO.getAgentId());
		    agentPath = (sysAgent == null ? null : sysAgent.getAgentPath());
		}
		agentPath = AgentPathUtil.getAgentPathByRole(agentPath);
	
		sysSooidDO.setAgentPath(agentPath);
		List<SysSooidDO> sooidList = sysSooidService.selectPage(sysSooidDO);
		return PageResult.ok(sooidList, page.getTotal());
	}

	
	/**
	 * 
	 * @param sysAuthVO
	 * @return
	 */
	@CrossOrigin
	@ApiOperation(value = "查询帐户详情", notes = "查询帐户详情")
	@RequestMapping(value="/selectById/{id}")
	@ApiModelProperty(value = "查询帐户详情")
	public Result selectById(@PathVariable("id")  Integer id){
		SysSooidDO sooidDO = sysSooidService.selectById(id);
		return Result.ok(sooidDO);
	}
	
	   /**
     * 
     * @param sysAuthVO
     * @return
     */
    @CrossOrigin
    @ApiOperation(value = "删除账号", notes = "删除账号")
    @RequestMapping(value="/delete")
    @ApiModelProperty(value = "删除账号")
    public Result delete(Integer id){
        sysSooidService.deleteById(id);
        return Result.ok();
    }


	
	/**
	 * TODO 未测试
	 * 方法1、刷新用户权限，角色
	 * 方法2、 删除redis 对应redis key 角色: shiro_roles_{id}, 登录用户: shiro:user:{id}
	 * @return
	 */
	public Result reflush(String userId, String username){
		//重新修改权限后清楚缓存，调用doGetAuthorizationInfo重新取角色的权限信息
//		RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
//		UserRealm shiroRealm = (UserRealm)rsm.getRealms().iterator().next();
//		
//		Subject subject = SecurityUtils.getSubject(); 
//		String realmName = subject.getPrincipals().getRealmNames().iterator().next(); 
		log.info("reflush userId= {}",  userId);
		
//		//shiroRealm.clearAllCachedAuthorizationInfo2();//清楚所有用户权限
//		//第一个参数为用户名,第二个参数为realmName,test想要操作权限的用户 
//		SimplePrincipalCollection principals = new SimplePrincipalCollection(user.getEmail(),realmName); 
//		subject.runAs(principals); 
//		shiroRealm.getAuthorizationCache().remove(subject.getPrincipals()); 
//		shiroRealm.getAuthorizationCache().remove(user.getEmail()); 
//		subject.releaseRunAs();

		
		RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
		UserRealm myRealm = (UserRealm)rsm.getRealms().iterator().next();
		Subject subject = SecurityUtils.getSubject(); 
        String realmName = subject.getPrincipals().getRealmNames().iterator().next(); 
        //第一个参数为用户名,第二个参数为realmName,test想要操作权限的用户 
        SimplePrincipalCollection principals = new SimplePrincipalCollection(username,realmName); 
        subject.runAs(principals); 
        myRealm.getAuthorizationCache().remove(subject.getPrincipals()); 
        subject.releaseRunAs();

		return Result.ok();
	}

	/**
     * @return
     */
    @CrossOrigin
    @ApiOperation(value = "自动登录", notes = "自动登录")
    @RequestMapping(value = "/checkTokon")
    public Result checkTokon(String token) {
//        if(StringUtils.isBlank(token)){
//            return Result.error("token 未空");
//        }
//        Subject subject = SecurityUtils.getSubject(); 
//        SysSooidDO user = (SysSooidDO)subject.getPrincipal();
//        JSONObject json = JSONObject.parseObject(token);
//        String key = KeyUtil.keyOf(keyEnum.USER_OSS, json.getString("token"));
//        
        return Result.ok("");
    }
    
    
    /**
     * @return
     */
    @CrossOrigin
    @ApiOperation(value = "客户帐号密码重置", notes = "客户帐号密码重置")
    @RequestMapping(value = "/resetPwd")
    public Result resetPwd(Integer id, String oldPwd, String newPwd, String agNewPwd, String token) {
        if(!StringUtils.equals(newPwd, agNewPwd)){
            return Result.error("2次密码不一样");
        }
        if (StringUtils.isBlank(newPwd) || (newPwd.length() < 6 || newPwd.length() > 16)){
            return Result.error("新密码格式错误");
        }
        Subject subject = SecurityUtils.getSubject();
        SysSooidDO user = (SysSooidDO)subject.getPrincipal();
        if(!StringUtils.equals(MessageDigestUtil.MD5(oldPwd), user.getPassword())){
            return Result.error("原密码错误");
        }
        SysSooidDO sysSooidAddVO = new SysSooidDO();
        sysSooidAddVO.setId(id);
        sysSooidAddVO.setPassword(MessageDigestUtil.MD5(newPwd));
        sysSooidService.updateSysSooid(sysSooidAddVO);
        this.login(user.getUserName(), newPwd, "");
        return Result.ok("重置成功");
    }
    
    /**
     * 管理员重置密码(不是oss用户)
     * @return
     */
    @CrossOrigin
    @ApiOperation(value = "重置密码", notes = "系统重置密码")
    @RequestMapping(value = "/resetPwd4Admin")
    public Result resetPwd(Integer id, String password) {
        SysSooidDO soo = new SysSooidDO();
        soo.setId(id);
        soo.setPassword(MessageDigestUtil.MD5(password));
        sysSooidService.updateSysSooid(soo);
        return Result.ok("重置成功");
    }
}
